#include "common/elements/user.h"
#include "common/log/log.h"
#include "common/more/uuid.h"

#include "database/data_elements/data_user.h"

#include "data_controller.h"
#include "permission_manager.h"

PermissionManager::PermissionManager(std::shared_ptr<DataController> dataController)
    : m_dataController(dataController)
{
}

PermissionManager::~PermissionManager()
{
}

Uuids::Uuid PermissionManager::login(
    const std::string& userLogin,
    const std::string& password
)
{
    if (userLogin.empty() || password.empty())
    {
        LOG_WARN << "Ошибка авторизации — нет ни логина, ни пароля.";
        return Uuids::nilUuid();
    }
    const auto dataUser = m_dataController->userByLogin(userLogin);
    if (!dataUser)
    {
        LOG_WARN
            << "Ошибка авторизации — нет такого пользователя: "
            << userLogin;
        return Uuids::nilUuid();
    }
    const auto user = dataUser->elementCast<Elements::User>();
    if (user->isBlocked())
    {
        LOG_WARN
            << "Ошибка авторизации — пользователь заблокирован: "
            << userLogin;
        return Uuids::nilUuid();
    }
    if (!user->checkPassword(password))
    {
        LOG_WARN
            << "Ошибка авторизации — неверный пароль: "
            << userLogin;
        return Uuids::nilUuid();
    }
    const auto sessionUuid = m_sessionManager.createSession(user);
    LOG_INFO
        << "Успешный вход в систему, сессия: "
        << Uuids::uuidToString(sessionUuid)
        << " "
        << userLogin;
    return sessionUuid;
}

bool PermissionManager::logout(
    const Uuids::Uuid& sessionUuid
)
{
    if (Uuids::nilUuid() == sessionUuid)
    {
        LOG_WARN << "Ошибка выхода — сессия не задана.";
        return false;
    }

    std::string userLogin;
    if (auto user = m_sessionManager.userBySession(sessionUuid))
        userLogin = user->login();

    const bool result = m_sessionManager.removeSession(sessionUuid);
    if (result)
    {
        LOG_INFO
            << "Успешный выход из системы, сессия:"
            << Uuids::uuidToString(sessionUuid)
            << " "
            << userLogin;
    }
    else
    {
        LOG_WARN
            << "Выход из системы не выполнен — сессия не найдена, сессия:"
            << Uuids::uuidToString(sessionUuid)
            << " "
            << userLogin;
    }
    return result;
}

Elements::UserPtr PermissionManager::userBySession(const Uuids::Uuid& uuid)
{
    return m_sessionManager.userBySession(uuid);
}
